package com.piece.core.session.repository;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.session.data.redis.RedisFlushMode;
import org.springframework.util.Assert;

public abstract class SessionRepository {

    protected Integer maxInactiveIntervalInSeconds = 1800;
    protected String redisNamespace = "spring:session";
    protected String sessionCreatedChannelPrefix;
    protected String sessionDeletedChannel;
    protected String sessionExpiredChannel;
    protected RedisFlushMode redisFlushMode;
    protected int database;
    protected RedisTemplate redisTemplate;
    protected RedisOperations<Object, Object> sessionRedisOperations;
    protected RedisSerializer<Object> defaultRedisSerializer = new JdkSerializationRedisSerializer();
    protected ApplicationEventPublisher applicationEventPublisher = new ApplicationEventPublisher() {
        public void publishEvent(ApplicationEvent event) {
        }

        public void publishEvent(Object event) {
        }
    };

    public abstract String getSessionDeletedChannel();

    public abstract String getSessionExpiredChannel();

    public abstract String getSessionCreatedChannelPrefix();

    public abstract void cleanupExpiredSessions();

    public abstract void setSessionRedisOperations(RedisOperations<Object, Object> sessionRedisOperations);

    private void configureSessionChannels() {
        this.sessionCreatedChannelPrefix = this.redisNamespace + "event:" + this.database + ":created:";
        this.sessionDeletedChannel = "__keyevent@" + this.database + "__:del";
        this.sessionExpiredChannel = "__keyevent@" + this.database + "__:expired";
    }

    public void setMaxInactiveIntervalInSeconds(Integer maxInactiveIntervalInSeconds) {
        this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
    }

    public void setRedisNamespace(String redisNamespace) {
        Assert.hasText(redisNamespace, "namespace cannot be null or empty");
        this.redisNamespace = redisNamespace.trim() + ":";
        this.configureSessionChannels();
    }

    public void setRedisFlushMode(RedisFlushMode redisFlushMode) {
        Assert.notNull(redisFlushMode, "redisFlushMode cannot be null");
        this.redisFlushMode = redisFlushMode;
    }

    public void setDatabase(int database) {
        this.database = database;
        this.configureSessionChannels();
    }

    public void setRedisTemplate(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        Assert.notNull(applicationEventPublisher, "applicationEventPublisher cannot be null");
        this.applicationEventPublisher = applicationEventPublisher;
    }

    public void setDefaultRedisSerializer(RedisSerializer<Object> defaultRedisSerializer) {
        this.defaultRedisSerializer = defaultRedisSerializer;
    }
}
